package com.zilu.digitaltwin.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zilu.digitaltwin.common.constants.CommonConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @author :caijianbao
 * @date : 2023/1/17 17:24
 */
@Aspect
@Component
@Slf4j
public class ControllerAspectConfig {

    @Pointcut("execution(public * com.zilu.digitaltwin.controller..*Controller.*(..))")
    public void controller() {
    }

    @Around("controller()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        String requestId;
        if (StringUtils.isNotBlank(request.getHeader(CommonConstants.REQ_ID))) {
            requestId = request.getHeader(CommonConstants.REQ_ID);
        } else if (StringUtils.isNotBlank(request.getParameter(CommonConstants.REQ_ID))) {
            requestId = request.getParameter(CommonConstants.REQ_ID);
        } else {
            requestId = UUID.randomUUID().toString().replace("-", "");
        }
        MDC.put(CommonConstants.REQ_ID, requestId);

        //获取代理地址（格式类似于"192.168.0.1"）、请求地址、请求类名、方法名
        String ipAddress = request.getRemoteAddr();
        String pathUrl = request.getRequestURI();
//        String methodName = proceedingJoinPoint.getSignature().getName();
//        String clazzName = proceedingJoinPoint.getTarget().getClass().getSimpleName();

        MethodSignature ms = (MethodSignature) proceedingJoinPoint.getSignature();
        //获取请求参数类型
        String[] parameterNames = ms.getParameterNames();
        //获取请求参数值
        Object[] parameterValues = proceedingJoinPoint.getArgs();
        StringBuilder paramSb = new StringBuilder();
        //组合请求参数，进行日志打印
        if (parameterNames != null && parameterNames.length > 0) {
            for (int i = 0; i < parameterNames.length; i++) {
                if (parameterNames[i].equals("bindingResult")) {
                    break;
                }
                if ((parameterValues[i] instanceof HttpServletRequest) || (parameterValues[i] instanceof HttpServletResponse)) {
                    paramSb.append("[").append(parameterNames[i]).append("=").append(parameterValues[i]).append("]");
                } else {
                    paramSb.append("[").append(parameterNames[i]).append("=")
                            .append(JSON.toJSONString(parameterValues[i], SerializerFeature.WriteDateUseDateFormat)).append("]");
                }
            }
        }
        Object result;
        try {
            result = proceedingJoinPoint.proceed(parameterValues);
        } catch (Exception e) {
            log.error("接口调用报错, requestId:{}, pathUrl:{}, 请求参数:{}",requestId, pathUrl, paramSb.toString());
            throw e;
        }
        long endTime = System.currentTimeMillis();
        log.info("requestId:{}, ip:{}, 请求接口{}, 耗时:{} ms, 请求参数:{}",
                requestId, ipAddress, pathUrl, endTime - startTime, paramSb.toString());
        return result;
    }

}
